package com.gallop.akka;

import com.gallop.akka.serialize.SerializerType;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.io.Resource;

import java.util.Arrays;
import java.util.List;

/**
 * Akka properties
 *
 * @author pipi
 */
@ConfigurationProperties(
        prefix = "akka"
)
@Getter
@Setter
public class AkkaProperties {

    private String systemName;
    /**
     * akka configuration, such as classpath:/akka-actor-system-1.conf
     */
    private Resource conf;
    /**
     * actor provider: local, remote, cluster，cluster_sharding
     */
    private ActorProviderType actorProvider;
    /**
     * akka remote local listen host
     */
    private String listenHost = "localhost";
    /**
     * akka remote local listen port
     */
    private Integer listenPort = 25600;

    private ListenPortCombineMethod portCombineMethod = ListenPortCombineMethod.ADD_SERVER_PORT;
    /**
     * cluster seed-nodes, such as akka.tcp://ClusterSystem@127.0.0.1:2551, akka.tcp://ClusterSystem@127.0.0.1:2552
     */
    private List<String> clusterSeedNodes;
    /**
     * cluster role definition for cluster-sharding
     */
    private String clusterRole = "cluster-node";

    /**
     * cluster sharding entity passivation(seconds. <=0 turning off)
     */
    private Long passivateIdleEntityAfter = 90L;
    /**
     * akka extensions
     */
    private List<String> extensions;

    /**
     * use serializer in {@link SerializerType}.
     * if false is set, using java-serializable {@link java.io.Serializable} by default
     */
    private Boolean enableSerializer = false;
    private SerializerType serializerType = SerializerType.jackson_json;
    private List<Class<?>> serializeExtraMessages;

    /**
     * cluster heartbeat failure tolerance
     */
    private Long heartbeatPause = 10L;

    @FunctionalInterface
    public interface ListenPortCombiner {

        Integer combine(Integer... ports);
    }

    @Getter
    public enum ListenPortCombineMethod {
        ORIGIN((ports) -> ports[0]),
        ADD_SERVER_PORT(ports -> Arrays.stream(ports).reduce(0, Integer::sum)),

        ;
        private final ListenPortCombiner combiner;

        ListenPortCombineMethod(ListenPortCombiner combiner) {
            this.combiner = combiner;
        }
    }
}
